“暂时性死区”(Temporal Dead Zone,简称 TDZ)是一个专门针对 let 和 const 的概念。
用 let 或 const 声明一个变量时,这个变量从代码块开始,一直到代码执行到声明语句的这一中间区域,就叫做“暂时性死区”。
访问变量
如果你在暂时性死区内尝试访问这个变量,JavaScript 会直接抛出一个 ReferenceError(引用错误),告诉你这个变量无法在初始化之前被访问。
核心机制
这和我们熟悉的 var 有很大的不同:
var的变量提升(Hoisting): 使用var声明的变量会被提升到作用域顶部,并且默认初始化为undefined。所以在声明之前访问它,你只会得到undefined,不会报错。let/const的变量提升: 其实它们也会被提升!但是,它们不会被默认初始化。引擎知道这个变量存在,但在代码运行到声明语句(比如let a = 1)之前,禁止你访问它。
出更健壮的代码而做的改进:
- 减少隐蔽的 Bug: 如果使用
var,你在声明前拿到undefined可能会误以为逻辑正常,但实际上是因为变量还没赋值。TDZ 强制要求你必须“先声明,后使用”,一旦顺序错了直接报错,能让你立刻发现代码逻辑的问题。 - 保证
const的语义: 对于常量const来说,它必须在声明的同时赋值。如果在声明前允许访问,那访问到的肯定是个空值,这违背了常量的设计初衷。
代码示例
看下面这个例子就非常直观了:
// --- 暂时性死区开始 ---
// ❌ 报错!ReferenceError: Cannot access 'myVar' before initialization
console.log(myVar);
// --- 暂时性死区结束 ---
let myVar = 'Hello'; // 声明并初始化,死区解除
// ✅ 正常输出 'Hello'
console.log(myVar);
如果你把上面的 let 换成 var:
// ✅ 不会报错,输出 undefined
console.log(myOldVar);
var myOldVar = 'World';
函数默认值的死区
除了明显的上下顺序,函数的默认参数也会形成暂时性死区。
// 这里的 b 的默认值依赖于 a
// 但在参数列表中,a 还没有被声明/初始化
function test(a = b, b = 2) {
console.log(a, b);
}
test(); // ❌ 报错!ReferenceError: Cannot access 'b' before initialization